{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "044d93cf",
   "metadata": {},
   "source": [
    "# 这里是YOLOV2的笔记"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3163b9eb",
   "metadata": {},
   "source": [
    "定位性能，小目标密集目标，recall都比较差。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "598f1359",
   "metadata": {},
   "source": [
    "## 1.1 Batch Normalization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "52e835b5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# <img src=\"./picture/.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a98b14a6",
   "metadata": {},
   "source": [
    "<img src=\"./picture/40.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df29622b",
   "metadata": {},
   "source": [
    "在V1版本的基础上，首先对数据做的就是标准化，用的是Z-score标准化。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b149402",
   "metadata": {},
   "source": [
    "## 1.2 理解batch Normalization"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2d06aad",
   "metadata": {},
   "source": [
    "<img src=\"./picture/41.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1dc907fd",
   "metadata": {},
   "source": [
    "上面的图片也讲述了python是怎么对数据进行Batch Normalization的：\n",
    "\n",
    "1.一个batch输入之后，对这个batch数量的数据进行标准化\n",
    "\n",
    "2.在预测阶段，用以及训练好的参数来求出最终的输出值。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c16aca56",
   "metadata": {},
   "source": [
    "标准化之后加快收敛的速度"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e9a21c0d",
   "metadata": {},
   "source": [
    "## 2.1 High Resolution Classifier (高分辨率的分类器)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4bf0c613",
   "metadata": {},
   "source": [
    "<img src=\"./picture/42.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "751a86c7",
   "metadata": {},
   "source": [
    "在传统的分类器上面，使用的一般是224 * 224大小的图片进行分类，但是yolo算法是在448 * 448上面\n",
    "进行分类的，所以这里就会有一个分辨率的问题。如果一开始就使用448 * 448 的网络架构对图片进行\n",
    "分类，这个时候就可以弱化分辨率的问题。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "35edf9f8",
   "metadata": {},
   "source": [
    "## 3.1 Anchor机制（应该也是最重要的机制）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47a3efd5",
   "metadata": {},
   "source": [
    "<img src=\"./picture/43.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f39b6d62",
   "metadata": {},
   "source": [
    "这里要介绍的是anchor机制：\n",
    "\n",
    "1.在V1版本中，每一个grid_cell都会生成两个框，但是这两个框没有训练之前是随机的，杂乱的。然后要\n",
    "不断的训练才可以很好的去拟合。\n",
    "\n",
    "2.在V2版本中，我们首先就定义了两个框（一个高瘦，一个矮胖），这个优点就是，如果检测的物体中含有高瘦或者矮胖，那么就会更加精确的将其检测出来\n",
    "当然，这个框的大小也是提前弄出来的，后面的论文应该是会讲述的。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db9eeeac",
   "metadata": {},
   "source": [
    "## 3.2 Anchor的例子"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e5d002c",
   "metadata": {},
   "source": [
    "<img src=\"./picture/44.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81b5825b",
   "metadata": {},
   "source": [
    " 这里可以解释一下上面说的Anchor的例子;\n",
    "\n",
    "1.这里每一个gridcell里面都有5个Boundingboxes,这5个boxes都有对应的Anchor,如上面的图所示。\n",
    "\n",
    "2.比如我要检测图片中的小女孩，这个小女孩的训练集中心点落在了一个gridcell里面，这个中心点有一个训练集标记好的\n",
    "gridtruth，然后就要从一开始就检测这5个Boundingboxesy与gridtruth的IoU，哪个打就选择哪个。\n",
    "\n",
    "3。最后只要选定这个Boundingboxes，然后不断利用损失函数来计算偏移量即可。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b0dbe30",
   "metadata": {},
   "source": [
    "## 4.1奇数的feature map"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aefda3bf",
   "metadata": {},
   "source": [
    "<img src=\"./picture/45.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "edb7e88e",
   "metadata": {},
   "source": [
    "在这里，将原始的图片划分成一个奇数乘以奇数的框架，至于为什么要这么划分，原因之一就是假如这张\n",
    "图片是占据主导的地位，那么就不会出现中心点出现在如右边的那种情况，就是说这个中心点可能会落在gridcell的交点上面。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a08405c0",
   "metadata": {},
   "source": [
    "## 5.1 V2版本的输出结果"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0c10ff64",
   "metadata": {},
   "source": [
    "<img src=\"./picture/46.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d055118e",
   "metadata": {},
   "source": [
    "<img src=\"./picture/47.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d76163ff",
   "metadata": {},
   "source": [
    "上面是V2版本的输出结果，和V1版本的输出结果还是有很大的不同的：\n",
    "\n",
    "1.对于V1版本，前面的置信度表示的是这个Boundingboxes中是否含有物体，然后再乘以后面的类别\n",
    "在V2版本中，每一个Anchor(这个时候类别归Anchor管)后面都有一个类别。每一个gridcell里面有5个Anchor.\n",
    "对于这个gridcell，每一个gridcell产生25 * 5 个数字。\n",
    "\n",
    "\n",
    "2.在上面的第二张图片，更加的介绍了V2版本的模型，使用的是一个darknet网络黑箱，然后上面的$c$表示的是\n",
    "分类的类别，$k$表示的是Anchor的数量。他的划分是13 * 13 ，所以输出向量是 13 * 13 * 25 * 5\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1799c165",
   "metadata": {},
   "source": [
    "## 6.1 手动Anchor的选择方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8c80f6e",
   "metadata": {},
   "source": [
    "<img src=\"./picture/48.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31de3a55",
   "metadata": {},
   "source": [
    "在之前就很好奇，这个Anchor的大小是怎么进行认为定义的。在拿到一个数据集的时候，会告诉你框的信息，\n",
    "我们可以根据这个框的信息来选择不同大小的框。这里可以使用聚类，将不同大小的框架进行聚类，然后画出那个什么肘部图还是什么山崖落实图...\n",
    "这里折中没如果Anchor的数量过于庞大会使模型复杂，所以选择5."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b8f0ad40",
   "metadata": {},
   "source": [
    "## 7.1 限制预测框的位置"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4663657",
   "metadata": {},
   "source": [
    "<img src=\"./picture/49.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f17c00dc",
   "metadata": {},
   "source": [
    "因为在V1的版本里面可以知道，每一个gridcell都会生成两个框，但是这两个框是乱窜的，野蛮生长的。在V2版本里面，中心点在这个gridcell里面应该是堆积生成的，也会出现乱窜的现象，所以要限制范围。\n",
    "\n",
    "这里使用了sigmoid函数来防止其乱窜，上面的$t_x,t_y$表示的是偏移量，这个偏移量可以是任意值，直接把他使用sigmoid函数限制在0~1之间，这个时候就不会出了gridcell那个框，由于$b_w,b_h$是任意大小的，所以不做限制。\n",
    "$c_x,c_y$是原始位置。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d4285f2",
   "metadata": {},
   "source": [
    "## 8.1 V2损失函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07eca756",
   "metadata": {},
   "source": [
    "<img src=\"./picture/50.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa9ae1b9",
   "metadata": {},
   "source": [
    "上面讲述了V2版本的损失函数：\n",
    "\n",
    "1.在这里先要说明一下损失函数中的一些特殊符号：\n",
    "\n",
    "首先是那些黄色的，只要满足条件就是1，不满足就是0. $\\lambda$表示的是一些权重.\n",
    "\n",
    "2.介绍第一个损失函数：首先是求和，表示的是遍历所有的gridcell以及所有的Anchor(每一个gridcell里面有A个Anchor)\n",
    "接下来就是将Anchor的中心点与训练集的中心点重合，选出$IoU < 0.6$的Anchor.只要$IoU$小于0.6，那么就要使用后面的损失函数，\n",
    "后面的$-b_{ijk}^{0}$表示的是$0 - b_{ijk}$就是说，你这个框因为$IoU$小于0.6，证明拟合的不是很好，我希望你这个置信度误差越小越好，最好在直接等于0.（每一个Anchor都有一个置信度）\n",
    "\n",
    "3.第二个损失函数，首先前面的黄色的东西表示的是迭代次数是否小于12800（说人话就是是否处于训练初期，处于训练初期要使用这个损失函数），\n",
    "后面的求和和V1版本是一样的，中心带你以及Anchor的宽高尽可能的拟合训练集\n",
    "\n",
    "4.第3个损失函数开始要注意！前面有一个黄色的标出来的，表示的是后面3个损失函数都是服务于拟合最好的那个Anchor（$ioU$与训练集的最大的那个）\n",
    "表示的是只要是这个$ioU$最大的Anchor就是1，否则为0.\n",
    "\n",
    "5.第3个损失函数的意义：选中的这个框和训练集的那个框尽可能的接近，和上面第二个一样\n",
    "\n",
    "6.第4个损失函数：标注框（训练集的框）和预测出来的Anchor的$IoU$减去1（这个$b_{ijk}^{o}就是等于1$\n",
    "）\n",
    "\n",
    "7.第5个损失函数：这个损失函数是类别的损失函数，遍历每个类别，然后输出标注类别与预测类别的误差（本质感觉和softmax很像）\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd1b9138",
   "metadata": {},
   "source": [
    "## 9.1 Fine-Grained Features(细粒度特征)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9f7f07c",
   "metadata": {},
   "source": [
    "<img src=\"./picture/51.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "644bf500",
   "metadata": {},
   "source": [
    "这里将数据拆分成了两份：\n",
    "\n",
    "1.一份按照常规的黑箱，另外一份直接将其拆分成 4 * 4 * 13 * 13 \n",
    "\n",
    "2. 然后最后直接拼接起来（这个样子可以加大对小目标检测的效果）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3bd590e6",
   "metadata": {},
   "source": [
    "<img src=\"./picture/52.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39633164",
   "metadata": {},
   "source": [
    "上面的图片讲述了在V2版本中的细粒度特征，说白了我感觉很像残差网络...."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b223bc3f",
   "metadata": {},
   "source": [
    "## 10.1 Multi-Scale Training "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0443d30c",
   "metadata": {},
   "source": [
    "<img src=\"./picture/53.png\" alt=\"Drawing\" style=\"width: 500px;\" align=\"left\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f53dd602",
   "metadata": {},
   "source": [
    "这里使用了一个东西，在V2版本的后面使用了一个平均池化层，这个样子可以保证后续的输出结果是一致的\n",
    "\n",
    "这样子会有一个缺点：高分辨率速度慢精度高，低分辨率速度快精度差。但是一般可以使用高分辨率。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "301b0f16",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e026556c",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5008f9be",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
